fix: keep qa report and artifact listings inside the protocol frame - #83
Merged
Conversation
Closes #14. A full diagnostic report is 500 events, each holding up to a 4 KiB message and an 8 KiB URL — roughly 2 MB against a 1 MiB frame. Encoding threw inside handleClient, fell into the generic catch, and the agent received INVALID_REQUEST for a request the host had accepted and executed. artifacts list had the same unbounded exposure as the store grew. Both responses are now bounded and say so. qa report trims its issue and event arrays to a byte budget, keeping the newest, while summary counts continue to describe every collected event so the numbers stay honest when the payload is trimmed. artifacts list returns the newest 250 with total and omitted counts. Both set truncated, matching the pruning contract used everywhere else. The transport now distinguishes a response that cannot be framed from a bad request: it answers RESPONSE_TOO_LARGE with a suggestion instead of blaming the caller. That path should now be unreachable for these two commands, but it is the honest fallback for any future response that outgrows the frame. Tests build a report that would previously have exceeded the frame and a store of 260 artifacts, and assert both encode within headlessMaximumMessageBytes with correct omitted accounting. P1 documents the bounds.
CI caught the first attempt: the issues array was capped at 100 entries but not by size. Issues are derived from the same events and carry the same 4 KiB message and 8 KiB URL, so 100 of them is over a megabyte on its own and the report still failed to frame. Both arrays now share one byte-budget helper. The test asserts issue accounting as well as event accounting, which is the assertion that would have caught this the first time.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #14.
The bug
A full diagnostic report is 500 events, each holding up to a 4 KiB message and an 8 KiB URL — roughly 2 MB against a 1 MiB frame.
encodeLinethrew insidehandleClient, fell into the genericcatch, and the agent received:…for a request the host had accepted and executed successfully. There was no escape hatch: no pagination, no way to ask for less.
artifacts listhad the same unbounded exposure as the store grew over a long session.The fix
Bounded responses that say what they dropped, matching the pruning contract used everywhere else in the product:
qa reporttrims itsissuesandeventsarrays to a byte budget, keeping the newest — those are what an agent is diagnosing. Crucially thesummarycounts still describe every collected event, so the numbers stay honest when the payload is trimmed.artifacts listreturns the newest 250 withtotalandomitted.truncated.The transport now separates "this response cannot be framed" from "your request was bad", answering
RESPONSE_TOO_LARGEwith a suggestion (--limit, orheadless qa clear). That path should be unreachable for these two commands now, but it is the honest fallback for any future response that outgrows the frame.Tests
Two new cases in the protocol suite: a report built from 500 × 4 KiB events, and a store holding 260 artifacts. Both assert the encoded response fits
headlessMaximumMessageBytesand that kept + omitted accounts for everything. The first fails onmain.Design note
Per architecture decision §4, response-side bounding was already sanctioned as a compatible addition, so no new decision entry is needed. I chose truncation now over cursor pagination: it is compatible, needs no wire-visible protocol addition, and makes the failure mode honest immediately. Cursor pagination is the richer answer and stays tracked as §G3 — worth doing when
console list/network listwant the same primitive.